import { RequestMethod } from './defines';
import Member, { MemberQuery } from '../Member'
import Room, { RoomQuery } from '../Rooms'
import kurentoClient from '../client'

enum RoomType {
  RESIDENT = 0,
  TEMPORARY = 2,
}

interface LoginParams {
  classType: RoomType;
  classId: string;
  classname: string;
}

interface offerQuery {
  /**
   * 用户 sdpOffer
   */
  offer: string;

  /**
   * 所属用户
   */
  member: MemberQuery;

  /**
   * 所属房间
   */
  room: RoomQuery;
}

// resident: 常驻房间
// temporary: 临时房间
export default function(app) {
  const { socket } = app.locals;
  const { userId } = socket.handshake.query;

  /**
   * 用户上线后 - 登录
   *
   * TODO 用于创建 常驻房间
   * @params userId 用户 ID
   * @params residentId 常驻房间 ID
   */
  socket.on(RequestMethod.login, function(data: LoginParams, cb) {
    const { classId, classname } = data;
    const { residentRooms, members } = app.locals;

    // console.log(members);
    members[userId].setResidentId(classId + '');

    // 加入 常驻房间
    socket.join(data.classId);

    // 储存常驻房间用户列表
    if (!residentRooms[data.classId]) {
      residentRooms[data.classId] = new Room(socket, classId, classname)
    }
    residentRooms[data.classId].setMember(members[userId]);

    const residentRoom = residentRooms[data.classId].getMembers();

    // 通知当前房间的其他人，但是自己并不收到消息
    socket.broadcast.to(data.classId).emit('online', {
      status: 'ok',
      data: residentRoom
    } as any);

    // 回调
    if (cb) {
      cb({ status: 'ok', resolve: 'logged', data: residentRoom })
    }
  });

  socket.on(RequestMethod.create, function(data, cb) {
    const { room, mediaOptions, mode, owner } = data;
    const { medias } = app.locals;

    // 媒体信息
    medias[room.classId] = mediaOptions;

    const clientUtils = kurentoClient((error) => { });
    app.locals.clientUtils = clientUtils;
    // 创建客户端 - socket 连接
    clientUtils.getClient((error, __client) => {
      if (error) return;
      app.locals.client = __client;

      // TODO 通知成员加入
      data.members.forEach(({userId}) => {
        const member = app.locals.members[userId as string];
        // console.log(member, data);
        if (member && member.userId !== owner.userId) {
          const options = { room, mode, mediaOptions };

          socket.timeout(10 * 1000).to((member as Member).socketId).emit('invite', options, (error, [data]) => {
            if (error) return;
            socket.emit('invited', { data: member, status: data.status });
            socket.broadcast.in(room.classId).emit('invited', { data: member, status: data.status });
            console.log('callback: => ', error, data, member)
          })
        }
      });

      // 回调
      if (cb) {
        cb({ status: 'ok', resolve: 'created' })
      }
    });
  });

  socket.on(RequestMethod.join, function(data, cb) {
    const { classId, classname } = data.room;
    const { temporaryRooms, medias, clientUtils, client } = app.locals;

    // 加入 临时房间
    socket.join(classId);
    // 媒体信息
    medias[classId] = data.mediaOptions;

    const owner = app.locals.members[userId];

    clientUtils.initEndpoint(client, (endpoint, pipeline) => {

      app.locals.members[userId].pipeline = pipeline;
      app.locals.members[userId].setEndpoint(userId, endpoint);
      clientUtils.onIceCandidate(endpoint, (iceCandidate) => {
        socket.emit('iceCandidate', { iceCandidate, member: owner.json() });
      });

      // 储存临时房间用户列表
      if (!temporaryRooms[classId]) {
        temporaryRooms[classId] = new Room(socket, classId, classname)
      }

      // 回调
      if (cb) {
        cb({
          status: 'ok',
          resolve: 'joined',
          data: temporaryRooms[classId].getMembers()
        })
      }
    });
  });


  /**
   * origin: 流的来源
   * target: 流向的目标
   */
  socket.on(RequestMethod.offer, function(data: offerQuery, cb) {
    const { offer, member, room } = data;
    const { temporaryRooms, clientUtils, members } = app.locals;
    const __member = members[member.userId];
    const endpoint = __member.getEndpoint(member.userId);

    // console.log(member, userId);
    __member.setClass(room.classId, room.classname);
    // 加入 临时房间
    temporaryRooms[room.classId].setMember(__member);
    if (member.userId === userId) {
      /**
       * 自己的 offer
       */
      clientUtils.processOffer(endpoint, offer, (sdpAnswer) => {

        socket.emit('answer', { sdpAnswer, member: __member.json() });
        // 通知当前房间的其他人，但是自己并不收到消息
        socket.broadcast.to(room.classId).emit('joined', members[userId].json());
      });
    } else {
      /**
       * 其他人的 offer
       */
      clientUtils.createEndpoint(__member.pipeline, (targetEndpoint) => {

        clientUtils.onIceCandidate(targetEndpoint, (iceCandidate) => {
          socket.emit('iceCandidate', { iceCandidate, member: __member.json() });
        });

        clientUtils.processOffer(targetEndpoint, offer, (sdpAnswer) => {
          clientUtils.connect(endpoint, targetEndpoint);
          __member.setEndpoint(userId, targetEndpoint);
          socket.emit('answer', { sdpAnswer, member: __member.json() });
        });
      });
    }

    // 回调
    if (cb) {
      // console.log(kurento + '');
      cb({status: 'ok', resolve: 'offer' })
    }
  });

  socket.on(RequestMethod.iceCandidate, function(data, cb) {
    const { iceCandidate } = data;
    const __member = app.locals.members[userId];

    __member.getEndpoint(userId).addIceCandidate(iceCandidate);

    // cb && cb({status: 'ok', resolve: 'iceCandidate' });
  })

}
